<template>
  <view class="image-upload-container">
    <!-- 图片区域 -->
    <scroll-view scroll-x="true" class="upimage_add" show-scrollbar="false">
      <view class="image-list-container">
        <!-- 图片 -->
        <view class="image-item-container" v-for="(item, index) in imageList" :key="index">
          <!-- 图片 -->
          <image class="image-container" mode="aspectFill" :src="item.localPath"></image>

          <!-- 上传进度遮罩层 -->
          <view v-if="item.percent >= 100" @click.stop="handlePrevieimg(index)" class="mask-container">
            <image src="/static/message-icon/mask.png" mode=""></image>
          </view>
          <view v-else class="mask-container"> {{item.percent}}% </view>

          <!-- 删除按钮 -->
          <view class="del-image-container" @click.stop="handleRemoveImg(index)">
            <uni-icons custom-prefix="iconfont" type="icon-cross" color="#fff" size="20rpx" style="line-height: 0;">
            </uni-icons>
          </view>
        </view>
        <!-- 上传按钮 图片数量超过9或等于9 不显示 -->
        <view class="up-btn" @click="handleUploadImage" v-if="imageList.length<count">
          <uni-icons custom-prefix="iconfont" type="icon-add" color="#545454" size="56rpx">
          </uni-icons>
        </view>
      </view>
    </scroll-view>
  </view>
</template>
<script>
  import {
    removeImageApi
  } from "@/api/common/index.js"
  import {
    HOST_URL
  } from "@/api/index.js"
  export default {
    name: "image-upload",
    data() {
      return {
        // 最大上传数量
        count: 9,
        // 图片列表
        imageList: [],
        // 最新上传索引位置
        imageUploadCurrent: 0,
        // 当前上传状态 true-默认状态 false-有文件正在上传中
        status: true,
      };
    },
    mounted() {
      this.status = true;
    },
    methods: {
      // 开始上传图片  可删
      handleUploadImage() {
        // 固定最多九张图
        const _count = this.count;
        // 图片大小
        const _MaxSize = 2 * 1024 * 1024;
        if (this.imageList.length >= _count) {
          this.handleShowToast("最多上传九张图片");
          return;
        }
        // 计算剩余可上传图片数量
        const count = _count - this.imageList.length;
        // 选择图片
        uni.chooseImage({
          count: count,
          sizeType: ['original', 'compressed'],
          sourceType: ['camera', 'album'], //从相册选择
          success: (res) => {
            this.status = false;
            this.handleChangeEmit();
            // 解决h5端无法限制上传数量
            if (res.tempFiles.length > count) {
              this.handleShowToast("最多上传九张图片");
              return;
            }
            // 过滤超出限制大小的图片
            let tempFilePaths = res.tempFiles.filter((item) => {
              return item.size <= _MaxSize;
            });
            // 判断是否全部图片符合上传要求大小
            if (tempFilePaths.length != res.tempFiles.length) {
              this.handleShowToast("有部分图片超出限制大小，单图最大2M");
            }
            this.handleStartUpload(tempFilePaths);
          },
        });
      },
      // 图片上传
      async handleStartUpload(tempFilePaths) {
        // 需要上传的图片总数
        let imageCount = tempFilePaths.length;
        let removeArr = [];
        let _num = 0;
        // 因微信小程序不允许多文件上传，所以选择遍历执行单文件上传方法
        for (let index = 0; index < imageCount; index++) {
          let item = tempFilePaths[index];
          // 图片的临时地址
          let path = item.path;
          // 图片列表追加 初始值 
          this.imageList.push({
            // 图片临时地址
            localPath: path,
            // 服务器图片地址
            url: '',
            // 上传进度
            percent: 0,
          })
          // 发送图片上传请求
          this.reqUploadFile(path).then((res) => {
            // 获取当前上传图片地址在图片数组列表中的索引
            let index = this.imageList.findIndex(item => item.localPath == res.localPath);
            if (res.state) {
              this.imageList[index].url = res.url;
            } else {
              this.imageList.splice(index,
                1); // 名：使用hadleUploadTask().then()异步执行上传事件，对返回的结果进行处理，如果上传失败则将该图片信息从图片列表数组中删除
            }
            _num++
            if (_num >= imageCount) {
              this.status = true;
              this.handleChangeEmit();
            }
          })
        }
      },
      // 封装图片上传请求
      reqUploadFile(path) {
        // 名：将上传任务封装成一个Promise实例，以便在调用reqUploadFile方法时通过then异步执行获取接口返回的结果
        return new Promise((resolve) => {
          // 开始上传
          // 名：调用uni.uploadFile时参数中加入success/fail/complete回调函数可以返回一个上传任务对象uploadTask，通过该对象的onProgressUpdate方法可以获取当前上传任务的进度，从而实现图片上传显示进度条或百分比的功能
          // uni.uploadFil官方文档  https://uniapp.dcloud.net.cn/api/request/network-file.html#uploadfile
          let uploadTask = uni.uploadFile({
            url: HOST_URL + "/common/upload-file", //接口地址
            filePath: path,
            name: 'file',
            header: {
              "token": getApp().globalData.getUser().token
            },
            formData: {
              "file": 'tempFilePaths'
            },
            success: (uploadFileRes) => {

              let res;
              try {
                console.log(uploadFileRes);
                res = JSON.parse(uploadFileRes.data)
              } catch (e) {
                this.handleShowToast("上传出现了些小问题");
                resolve({
                  state: false,
                  url: "",
                  localPath: path
                });
                return;
              }
              if (res.success) {
                let url = res.data.url;
                resolve({
                  state: true,
                  url: url,
                  localPath: path
                });
              } else {
                // 上传失败
                resolve({
                  state: false,
                  url: "",
                  localPath: path
                });
              }
            },
            fail: () => {
              // 上传失败
              resolve({
                state: false,
                url: "",
                localPath: path
              });
            }
          });
          // 更新上传进度
          uploadTask.onProgressUpdate((res) => {
            let index = this.imageList.findIndex(item => item.localPath == path);
            console.log(this.imageList[index].percent);
            this.imageList[index].percent = res.progress;
          })
        })
      },
      // 预览图片  可删
      handlePrevieimg(index) {
        uni.previewImage({
          current: index,
          urls: this.imageList.map((item) => {
            return item.url;
          }),
        });
      },
      // 删除图片
      handleRemoveImg(index) {
        uni.showModal({
          title: '删除',
          content: '确定删除该图片？',
          success: async (res) => {
            if (res.confirm) {
              let url = this.imageList[index].url;
              // 名：此时图片已经上传到服务器中，调用后端删除图片接口将文件从服务器中删除是为了避免造成资源浪费。但是为了不违背用户删除图片的意愿影响后续文章发布，无论后端删除图片接口返回的结果是否成功，前端都会将图片从图片列表数组中删除。
              await removeImageApi(url);
              this.imageList.splice(index, 1)
              if (this.imageList.length == 0) {
                // 图片列表为空 恢复默认状态
                this.status = true
              }
              this.handleChangeEmit();
              // 名：图片删除成功后，调用handleChangeEmit方法，将最新的图片列表传递给父组件。
            }
          }
        });
      },
      // 上传回调事件
      handleChangeEmit() {
        let imagePaths = this.imageList.map((item) => {
          return item.url;
        })
        this.$emit('change', {
          data: imagePaths,
          status: this.status,
        });
      },
      // 提示
      handleShowToast(title) {
        uni.showToast({
          title: title,
          icon: "none"
        })
      }
    }
  }
</script>
<style lang="scss">
  .image-upload-container {

    // 图片列表
    .image-list-container {
      display: flex;
      flex-wrap: nowrap;

      // 图片
      .image-item-container {
        width: 210rpx;
        height: 210rpx;
        border-radius: 8rpx;
        position: relative;
        margin-right: 32rpx;
        flex-shrink: 0;

        image {
          width: 100%;
          height: 100%;
        }

        .image-container {
          border-radius: 16rpx;
        }

        .mask-container {
          width: 100%;
          height: 100%;
          border-radius: 8rpx;
          background: rgba(0, 0, 0, 0.4);
          color: white;
          position: absolute;
          top: 0;
          left: 0;
          display: flex;
          align-items: center;
          justify-content: center;

          image {
            width: 96rpx;
            height: 96rpx;
          }
        }

        .del-image-container {
          width: 40rpx;
          height: 40rpx;
          background-color: #000;
          position: absolute;
          top: 0rpx;
          right: 0rpx;
          border-radius: 0px 0px 0px 8rpx;
          display: flex;
          align-items: center;
          justify-content: center;
        }

      }

      // 上传按钮
      .up-btn {
        width: 210rpx;
        height: 210rpx;
        border-radius: 30rpx;
        background-color: #f6f6f6;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
      }
    }

  }
</style>